import numpy
import os
from scipy import spatial
import math
'''#########################################################'''
'''##################    Initialisation   ##################'''
'''#########################################################'''

# Number of model vectors
grid_nodes_num = 3
grid_dimentionality = 2
clusters_num = grid_nodes_num**grid_dimentionality
datafile = os.path.dirname(__file__) + '-files/features-100'

'''##########################################################################'''
'''##################    Distances between model vectors   ##################'''
'''##########################################################################'''
'''# initialise model vectors
if grid_dimentionality == 1:
    model_vectors = numpy.arange(clusters_num).reshape(grid_nodes_num)
if grid_dimentionality == 2:
    model_vectors = numpy.arange(clusters_num).reshape(grid_nodes_num, grid_nodes_num)
if grid_dimentionality == 3:
    model_vectors = numpy.arange(clusters_num).reshape(grid_nodes_num, grid_nodes_num, grid_nodes_num)'''

# Store SQUARED distances between vector models
grid_distances = numpy.zeros((clusters_num,clusters_num))
if grid_dimentionality == 1:
    model1 = 0
    for x1 in range(grid_nodes_num):
        model2 = 0
        for x2 in range(grid_nodes_num):
            squared_distance = (x1-x2)**2
            grid_distances[model1,model2]=squared_distance
            model2 += 1         
        model1 += 1
if grid_dimentionality == 2:
    model1 = 0
    for x1 in range(grid_nodes_num):
        for y1 in range(grid_nodes_num):
            model2 = 0
            for x2 in range(grid_nodes_num):
                for y2 in range(grid_nodes_num):
                    squared_distance = (x1-x2)**2+(y1-y2)**2
                    grid_distances[model1,model2]=squared_distance
                    model2 += 1         
            model1 += 1         
if grid_dimentionality == 3:
    model1 = 0
    for x1 in range(grid_nodes_num):
        for y1 in range(grid_nodes_num):
            for z1 in range(grid_nodes_num):
                model2 = 0
                for x2 in range(grid_nodes_num):
                    for y2 in range(grid_nodes_num):
                        for z2 in range(grid_nodes_num):
                            squared_distance = (x1-x2)**2+(y1-y2)**2+(z1-z2)**2
                            grid_distances[model1,model2]=squared_distance
                            model2 += 1         
                model1 += 1
   
'''-------------------------------- Step 1 --------------------------------------'''            
'''##############################################################################'''
'''##################    Load data, initialise model vectors   ##################'''
'''##############################################################################'''

def Init(datafile):
    datapoint = numpy.loadtxt(datafile)
    datapoints_num = datapoint.shape[0]
    datapoints_dimensionality = datapoints.shape[1]
    model_vectors = numpy.zeros((clusters_num, datapoints_dimensionality))
    
    for dimension in range(datapoints_dimensionality):    
        maxvalue = numpy.max(datapoints[:,dimension])
        minvalue = numpy.min(datapoints[:,dimension])
        vector = numpy.random.uniform(minvalue, maxvalue, clusters_num)
        model_vectors[:,dimension] = vector.T
    return datapoints, model_vectors



def AssignDatapoints(datapoints, model_vectors):
    cluster_to_datapoint = dict()
    distances_datapoints_to_clusters = spatial.distance.cdist(datapoints, model_vectors)
    datapoint_to_cluster = numpy.argmin(distances_datapoints_to_clusters, axis=1)
    for cluster in range(clusters_num):
        cluster_to_datapoint[cluster] = numpy.where(datapoint_to_cluster==cluster)[0]
    return datapoint_to_cluster, cluster_to_datapoint

sigma0 = 1
lambda_time = 0.5

def AssignModelvectors(datapoints,cluster_to_datapoint, time):
    sigma = sigma0*math.exp(-time/lambda_time)
    numpy.exp(-grid_distances/(2.0*sigma))
    
    
datapoints, model_vectors = Init(datafile)
AssignDatapoints(datapoints, model_vectors)